#include "antidebugutils.h"
#include <debugapi.h>
#include <processthreadsapi.h>
#include <tlhelp32.h>
#include <wchar.h>
#include <windows.h>
#include <winternl.h>

AntiDebugUtils::AntiDebugUtils()
{

}

bool AntiDebugUtils::anitDebug_isDebuggerPresent()
{
    return IsDebuggerPresent();
}

bool AntiDebugUtils::antiDebug_RtlGetNtGlobalFlags() {
    HMODULE ntdll = LoadLibraryA("ntdll.dll");
    FARPROC proc = GetProcAddress(ntdll, "RtlGetNtGlobalFlags");
    typedef ULONG (*RtlGetNtGlobalFlags_t)(void);
    return ((RtlGetNtGlobalFlags_t)proc)() & (0x20 | 0x40);
}

bool AntiDebugUtils::antiDebug_CheckRemoteDebuggerPresent() {
    BOOL isRemoteDebuggerPresent = FALSE;
    if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &isRemoteDebuggerPresent)) {
        return isRemoteDebuggerPresent;
    }
    return false;
}

bool AntiDebugUtils::antiDebug_DebugRegister() {
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    if (GetThreadContext(GetCurrentThread(), &ctx)) {
        return (ctx.Dr0 != 0 || ctx.Dr1 != 0 || ctx.Dr2 != 0 || ctx.Dr3 != 0);
    }
    return false;
}

void AntiDebugUtils::antiDebug_HideFromDebugger() {
    HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
    if (ntdll == NULL) {
        abort();
    }

    pfnNtSetInformationThread ntSetInfoThread = (pfnNtSetInformationThread)GetProcAddress(ntdll, "NtSetInformationThread");
    if (ntSetInfoThread == NULL) {
        abort();
    }

    ntSetInfoThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);
}

bool AntiDebugUtils::checkAntiDebug()
{

    antiDebug_HideFromDebugger();

    return anitDebug_isDebuggerPresent() || antiDebug_CheckRemoteDebuggerPresent() ||
    antiDebug_DebugRegister() ||  antiDebug_RtlGetNtGlobalFlags();
}

